home *** CD-ROM | disk | FTP | other *** search
/ NeXT Education Software Sampler 1992 Fall / NeXT Education Software Sampler 1992 Fall.iso / Mathematics / Notebooks / SigProc2.0 / Packages / SignalProcessing / ObjectOriented / Signal.m < prev    next >
Encoding:
Text File  |  1992-08-18  |  22.9 KB  |  731 lines

  1. (*  :Title:    Signal Objects "Signal.m"  *)
  2.  
  3. (*  :Authors:    Brian Evans, James McClellan  *)
  4.  
  5. (*  :Summary:    To provide signal specification a la Cory Myers.  *)
  6.  
  7. (*  :Context:    SignalProcessing`ObjectOriented`Signal`  *)
  8.  
  9. (*  :PackageVersion:  2.7    *)
  10.  
  11. (*
  12.     :Copyright:    Copyright 1989-1991 by Brian L. Evans
  13.         Georgia Tech Research Corporation
  14.  
  15.     Permission to use, copy, modify, and distribute this software
  16.     and its documentation for any purpose and without fee is
  17.     hereby granted, provided that the above copyright notice
  18.     appear in all copies and that both that copyright notice and
  19.     this permission notice appear in supporting documentation,
  20.     and that the name of the Georgia Tech Research Corporation,
  21.     Georgia Tech, or Georgia Institute of Technology not be used
  22.     in advertising or publicity pertaining to distribution of the
  23.     software without specific, written prior permission.  Georgia
  24.     Tech makes no representations about the suitability of this
  25.     software for any purpose.  It is provided "as is" without
  26.     express or implied warranty.
  27.  *)
  28.  
  29. (*  :History:    *)
  30.  
  31. (*  :Keywords:    *)
  32.  
  33. (*
  34.     :Source:         Myers, C.  {Signal Representation for Symbolic and
  35.         Numeric Processing}.  MIT Ph.D. Thesis. 1986.
  36.  *)
  37.  
  38. (*  :Warning:    *)
  39.  
  40. (*  :Mathematica Version:  1.2 or 2.0  *)
  41.  
  42. (*  :Limitation:  *)
  43.  
  44. (*
  45.     :Discussion:  All new functions have usage information.
  46.           This file builds upon "Slot.m", "Support.m".
  47.           This file is on the same level as "DSP.m", and "ZSupport.m"
  48.           Signals have a variable number of slots.
  49.           Slots defined by Cory Myers: (RealOrComplex --> DataType)
  50.               Bandwidth
  51.               CenterOfSymmetry
  52.               End
  53.               EndBandwidth
  54.               Period
  55.               Start
  56.               StartBandwidth
  57.               Support
  58.               Symmetry
  59.           Additional slots for all signals:
  60.               CurrentValue
  61.               Dimensions
  62.               Length
  63.           Additional slots for computable signals:
  64.               FrequencyVariables
  65.               Implementation
  66.               OutOfDomainValue
  67.               TheFunction
  68.               TimeVariables
  69.               ZTransData
  70.               ZVariables
  71.           Additional slots for stream signals:
  72.               CurrentIndex
  73.           Additional slots for array signals:
  74.               Array
  75.           Methods for signals:
  76.               Fetch
  77.               GetValue
  78.               Z
  79.           Methods for Stream signals:
  80.               NextFun
  81.               PreUpdateFunction
  82.               PostUpdateFunction
  83.  *)
  84.  
  85. (*
  86.     :Functions:      ArraySignal
  87.           ArraySignalQ
  88.           ComputableSignalQ
  89.           DiscreteTimeSignalQ
  90.           Fetch
  91.           GetValue
  92.           IIRFilter
  93.           MakeContinuousSignal
  94.           MakeDigitalSignal
  95.           MakeSignal
  96.           MyMakeSignal
  97.           PointwiseSignalQ
  98.           SignalQ
  99.           StreamSignal
  100.           StreamSignalQ
  101.  *)
  102.  
  103.  
  104.  
  105. (*  B E G I N     P A C K A G E  *)
  106.  
  107. BeginPackage[ "SignalProcessing`ObjectOriented`Signal`",
  108.           "SignalProcessing`ObjectOriented`Slot`",
  109.           "SignalProcessing`ObjectOriented`StackQueue`",
  110.           "SignalProcessing`Support`ROC`",
  111.           "SignalProcessing`Support`DataType`",
  112.           "SignalProcessing`Support`FilterSupport`",
  113.           "SignalProcessing`Support`SigProc`",
  114.           "SignalProcessing`Support`SupCode`" ]
  115.  
  116.  
  117. If [ TrueQ[ $VersionNumber >= 2.0 ],
  118.      Off[ General::spell ];
  119.      Off[ General::spell1 ] ];
  120.  
  121.  
  122. (*  U S A G E     I N F O R M A T I O N  *)
  123.  
  124. ArraySignal::usage =
  125.     "ArraySignal[oldsig, start, end] returns a new signal which has \
  126.     slots Start and End equal to start and end, respectively, and is \
  127.     array-based (Implementation slot is Array)."
  128.  
  129. ArraySignalQ::usage =
  130.     "ArraySignalQ[signal] returns True if the signal is array-based, \
  131.     which means that all signal values are computed at one time and \
  132.     stored."
  133.  
  134. CenterOfSymmetry::usage =
  135.     "CenterOfSymmetry[signal] returns the center-of-symmetry of the \
  136.     signal."
  137.  
  138. ComputableSignalQ::usage =
  139.     "ComputableSignalQ[signal] returns True if computational methods \
  140.     like Fetch are supported for the signal. \
  141.     This is true if the signal has an Implementation slot."
  142.  
  143. DiscreteTimeSignalQ::usage =
  144.     "DiscreteTimeSignalQ[signal] returns True if the signal is \
  145.     a discrete-time signal." 
  146.  
  147. EndBandwith::usage =
  148.     "EndBandwith[signal] retuns the end location of a signal's bandwidth. \
  149.     In the case of signals that are not band-limited, \
  150.     this function will return Infinity (the default)."
  151.  
  152. Fetch::usage =
  153.     "Fetch[signal, index] returns the value of the signal at index, \
  154.     where index can be a number (for one-dimensional signals) or a \
  155.     list of numbers (for multidimensional signals).  Fetch only \
  156.     works for computable signals which are arrayed, pointwise, and \
  157.     stream signals.  Stream signals also have an associated method \
  158.     called FetchNext.  If the signal is arrayed and if any one of \
  159.     the indices is an infinity, then the value of the signal's \
  160.     OutOfDomainValue slot will be returned."
  161.  
  162. FetchArray::usage =
  163.     "FetchArray[array_signal] ..."
  164.  
  165. FetchNext::usage =
  166.     "FetchNext[stream_signal] will return the next value in the stream \
  167.     of data represented by stream_signal."
  168.  
  169. IIRCoefficients::usage =
  170.     "IIRCoefficients is a special slot for infinite-impulse response \
  171.     digital filters. \
  172.     It simply contains a list of feedback coefficients."
  173.  
  174. IndependentVariable::usage =
  175.     "IndependentVariable[signal] returns the independent variable(s) \
  176.     involved in the signal's (functional) definition."
  177.  
  178. IIRFilter::usage =
  179.     "IIRFilter[p,a0,a][x] calculates the output of the IIR filter \
  180.     at discrete time n, where the input at time n is x.  The feedback\
  181.     coefficients are in the a vector and each is scaled by a0.  The \
  182.     list p is a table of the last L outputs, where L is the number of \
  183.     feedback coefficients."
  184.  
  185. IIRPostUpdate::usage =
  186.     "IIRPostUpdate is a special method just for IIR signals."
  187.  
  188. MakeContinuousSignal::usage =
  189.     "MakeContinuousSignal[] returns a signal object with the slot \
  190.     CONTINUOUS set to True."
  191.  
  192. MakeDigitalSignal::usage =
  193.     "MakeDigitalSignal[] returns a signal object with the slot \
  194.     DISCRETE set to True."
  195.  
  196. MakeSignal::usage =
  197.     "MakeSignal[] returns a signal object with one slot for system use. \
  198.     MakeSignal[var] returns a signal object with slot \
  199.     IndependentVariable set to var and with one slot defined for \
  200.     system use. \
  201.     MakeSignal[signal, n, property1, value, property2, value, ...] \
  202.     can be used to define a signal as a function of n (the properties \
  203.     are optional).
  204.     If the signal is multidimensional, n will be a list of variables \
  205.     (one for each dimension, like {n1, n2, n3} in the three-dimensional \
  206.     case). \
  207.     Possible signals include Impulse[n], Step[n], FIR[n, {h0, h1, ...}],
  208.     and IIR[n, {a0, a1, ...}]. See MyMakeSignal."
  209.  
  210. MyMakeSignal::usage =
  211.     "MyMakeSignal[signal, var] extends the possibilities of MakeSignal. \
  212.     It allows the definition of standard signals as a function of var. \
  213.     Signals defined this way include FIR[n, h0, h1, ...] and \
  214.     IIR[n, a0, a1, ...]."
  215.  
  216. NextFun::usage =
  217.     "NextFun is a method for stream-based signals describing how to \
  218.     compute the next value."
  219.  
  220. OutOfDomainValue::usage =
  221.     "OutOfDomainValue[signal] is the value to return if the signal is \
  222.     accessed outside of its region of support. \
  223.     This value defaults to zero."
  224.  
  225. PastValues::usage =
  226.     "PastValues is a slot that remembers previously computed signal values."
  227.  
  228. PointwiseSignal::usage =
  229.     "PointwiseSignal is a type of signal in which signal values are \
  230.     computed point-by-point. \
  231.     Such a signal does not depend on previous outputs or inputs."
  232.  
  233. PointwiseSignalQ::usage =
  234.     "PointwiseSignalQ[signal] returns True if the values of the \
  235.     signal are computed point-by-point, and the value at each \
  236.     point is independent of other values of the signal."
  237.  
  238. PostUpdateFunction::usage =
  239.     "PostUpdateFunction is a method which is applied to signal after \
  240.     each computation of a new signal value."
  241.  
  242. PreUpdateFunction::usage =
  243.     "PreUpdateFunction is a method which is applied to signal before \
  244.     each computation of a new signal value."
  245.  
  246. PrintName::usage =
  247.     "PrintName[signal] is the name of the signal which is what is output \
  248.     on the screen when the signal is to displayed."
  249.  
  250. RealOrComplex::usage =
  251.     "RealOrComplex[signal] returns True if the signal's output values \
  252.     are real-valued or complex-valued."
  253.  
  254. Self::usage =
  255.     "Self is a pre-defined slot that is bound to the entire object \
  256.     of which it is a member. \
  257.     It can be used as a variable in methods and slots."
  258.  
  259. Signal::usage =
  260.     "A signal is an object with head Signal. \
  261.     From the work of Cory Myers, possible slots include: \
  262.     Bandwidth, CenterOfSymmetry, End, EndBandwidth, Period, Start, \
  263.     StartBandwidth, Support, and Symmetry. \
  264.     Possible additional slots are: \
  265.     CurrentValue, DataType, Dimensions, FrequencyVariables, \
  266.     Implementation, Length, OutOfDomainValue, TheFunction, \
  267.     TimeVariables, ZTransData, ZVariables, CurrentIndex, \
  268.     NextFun, PreUpdateFunction, and PostUpdateFunction. \
  269.     Multidimensional signals are supported.  See MakeSignal."
  270.  
  271. SignalQ::usage =
  272.     "SignalQ[x] returns True if the head of x is Signal."
  273.  
  274. StartBandwith::usage =
  275.     "StartBandwith[signal] returns the starting location of the bandwidth \
  276.     of the signal. \
  277.     For signals that are not bandlimited, \
  278.     this method will return -Infinity which is the default value."
  279.  
  280. StreamSignal::usage =
  281.     "StreamSignal is a type of signal that computes its outputs one
  282.     after another usually without reference to past values."
  283.  
  284. StreamSignalQ::usage =
  285.     "StreamSignalQ[signal] returns True if the values of signal are \
  286.     computed one at a time in some order. \
  287.     The value at each point can be dependent on previously-computed \
  288.     values, state information, etc. \
  289.     Signals generated by finite state machines are stream signals."
  290.  
  291. (*  E N D     U S A G E     I N F O R M A T I O N  *)
  292.  
  293.  
  294. Begin["`Private`"]
  295.  
  296. (*  G L O B A L S  *)
  297.  
  298. arraysignal::dimensions = "Dimensions of start and end are different."
  299. Fetch::notcomputable = "Signal `` does not have computable values."
  300. MyMakeSignal::rect = "A rectangular window must have a positive length."
  301. oddlen::proplist = "Property list has odd number of terms."
  302. ztransform::notcomputable = "Signal `` does not have computable values."
  303. ztransform::notdiscrete = "`` is not a discrete-time signal."
  304. invztransform::notcomputable = "Signal `` does not have computable values."
  305. FIR::dimensions =
  306.     "Using a one-dimensional variable for a multidimensional signal."
  307.  
  308. (*  Do not evaluate arguments to Signal[] because  *)
  309. (*  Signal is a data tag and not a function.       *)
  310. DefObjectType[Signal]
  311.  
  312. (*  Prevents infinite loops; directs how operator[signal_object] is evaluated *)
  313. ClearStack[SignalOperatorSemaphore]
  314.  
  315.  
  316. (*  S U P P O R T I N G     R O U T I N E S  *)
  317.  
  318. (*  ArraySignal --  end is non-inclusive  *)
  319. ArraySignal[oldsig_, start_, end_, dims_] :=
  320.     Block [ {signal},
  321.         If [ ! SameQ[Dimensions[start], Dimensions[end]],
  322.              Message[arraysignal::dimensions]; Return[Null] ];
  323.         signal = oldsig;
  324.         signal = AddSlot[signal, False, Start, start];
  325.         AddSlot[signal, False, End, end];
  326.         AddSlot[signal, False, Length, end - start];
  327.         AddSlot[signal, False, Dimensions, dims];
  328.         AddSlot[signal, False, CenterOfSymmetry, (end - start - 1)/2];
  329.         AddSlot[signal, True,  CurrentValue, 0];
  330.         AddSlot[signal, False, Implementation, Array] ]
  331.  
  332. (*  ArraySignalQ  *)
  333. ArraySignalQ[signal_] := SignalQ[signal] && SameQ[Implementation[signal], Array]
  334.  
  335. (*  ComputableSignalQ  *)
  336. ComputableSignalQ[signal_] := HasSlotQ[signal, Implementation]
  337.  
  338. (*  DiscreteTimeSignalQ  *)
  339. DiscreteTimeSignalQ[x_] := SignalQ[x] && DISCRETE[x] && SameQ[Domain[x], Time]
  340.  
  341. (*  GetValue --  two argument, three argument, and main versions  *)
  342. Signal/: GetValue[Signal[slots__], index_] :=
  343.     GetValue[Signal[slots], TimeVariables[signal], index] 
  344.  
  345. Signal/: GetValue[Signal[slots__], n_, index__] :=
  346.     TheFunction[Signal[slots]] /.
  347.         { ReplaceWith[n, index], Self -> Signal[slots] }
  348.  
  349. (*  IIRFilter ::  input x[n], past n values p, feedback coefficients a  *)
  350. IIRFilter[p_, a0_, a_][x_] := x  -  Dot[p, a] / a0;
  351.  
  352. (*  IIRPostUpdate  *)
  353. SetAttributes[IIRPostUpdate, {HoldAll}]
  354.  
  355. IIRPostUpdate[signal_] :=
  356.     Block [ {newpast, pastvalues},
  357.         pastvalues = PastValues[signal];
  358.         If [ ListQ[pastvalues],
  359.              newpast = RotateRight[pastvalues];
  360.              newpast[[1]] = CurrentValue[signal],
  361.              newpast = CurrentValue[signal] ];
  362.         WriteSlot[signal, PastValues, newpast] ]
  363.  
  364. (*  MakeSignal  *)
  365. MakeSignal[] := MakeObject[Signal]
  366. MakeSignal[FIR[n_, h_List]] := MakeSignal[FIR[n, h], n]
  367. MakeSignal[c_] :=
  368.     Block [ {signal},
  369.         signal = MakeSignal[];
  370.         AddSlot[signal, False, TheFunction, c];
  371.         AddSlot[signal, False, DataType, DataType[c]];
  372.         AddSlot[signal, False, TimeVariables, n] ] /;
  373.     ConstantQ[c]
  374. MakeSignal[var_] :=
  375.     Block [    {signal},
  376.         signal = MakeSignal[];
  377.         AddSlot[signal, False, TimeVariables, var] ]
  378. MakeSignal[x_, n_:Global`n] :=
  379.     Block [    {datatype, signal},
  380.         signal = MyMakeSignal[x, n];
  381.         If [ SameQ[Head[signal], MyMakeSignal],
  382.              signal = MakeSignal[n];
  383.              AddSlot[signal, False, TheFunction, x] ];
  384.         If [ ! HasSlotQ[signal, DataType] && HasSlotQ[signal, TheFunction],
  385.              datatype = DataType[ReadSlot[signal, TheFunction]];
  386.              If [ DataTypeQ[datatype],
  387.                   AddSlot[signal, False, DataType, datatype] ] ];
  388.         signal ]
  389. MakeSignal[x_, n_, properties__] :=
  390.     Block [    {prop, signal},
  391.         signal = MakeSignal[x, n];
  392.         proplist = ToList[properties];
  393.         len = Length[proplist];
  394.         If [ OddQ[len], Message[oddlen::proplist] ];
  395.         For [ prop = 1, prop < len, prop += 2,
  396.               WriteSlot[signal, proplist[[prop]], proplist[[prop+1]]] ];
  397.         signal ]
  398.  
  399. (*  MakeDigitalSignal and MakeContinuousSignal  *)
  400. MakeDigitalSignal[n_:Global`n] :=
  401.     Block [    {signal},
  402.         signal = MakeSignal[];
  403.         signal = AddSlot[signal, False, TimeVariables, n];
  404.         AddSlot[signal, False, DISCRETE, True] ]
  405. MakeContinuousSignal[t_:Global`t] :=
  406.     Block [    {signal},
  407.         signal = MakeSignal[];
  408.         signal = AddSlot[signal, False, TimeVariables, t];
  409.         AddSlot[signal, False, CONTINUOUS, True] ]
  410.  
  411. (*  PointwiseSignalQ  *)
  412. PointwiseSignalQ[signal_] := SignalQ[signal] && SameQ[Implementation[signal], Pointwise]
  413.  
  414. (*  SignalQ  *)
  415. SignalQ[x_] := SameQ[Head[x], Signal]
  416.  
  417. (*  StreamSignal  *)
  418. StreamSignal[signal_, start_, end_] :=
  419.     Block [    {newsig},
  420.         newsig = signal;
  421.         AddSlot[newsig, False, Start, start];
  422.         AddSlot[newsig, False, End, end];
  423.         AddSlot[newsig, True,  CurrentIndex, start - 1];
  424.         AddSlot[newsig, False, Implementation, Stream] ]
  425.  
  426. (*  StreamSignalQ  *)
  427. StreamSignalQ[signal_] := SameQ[Implementation[signal], Stream]
  428.  
  429.  
  430. (*  B A S I C     S I G N A L S  *)
  431.  
  432. (*  FIR[n, {h0, h1, ...}] is the impulse response of a finite  *)
  433. (*  impulse response filter with coefficients h0, h1, ...      *)
  434. MyMakeSignal[FIR[n_, h_], n_] :=
  435.     Block [    {dims, dimensions, hlist, signal, start},
  436.         hlist = ToList[h];
  437.         dimensions = Dimensions[hlist];
  438.         dims = Length[dimensions];
  439.         start = Table[0, {dims}];
  440.         If [ dims == 1,
  441.              start = 0; dimensions = Length[hlist] ];
  442.         If [ dims > 1 && AtomQ[n],
  443.              Message[FIR::dimensions] ];
  444.         signal = ArraySignal[MakeDigitalSignal[n], start,
  445.                      dimensions, dims];
  446.         AddSlot[signal, False, PrintName, FIR[n, h]];
  447.         AddSlot[signal, False, TheFunction,
  448.             SequenceToFunction[hlist, n]] ];
  449.  
  450. (*    IIR[n, a0, a1, a2, ...] is the impulse response of an  *)
  451. (*  IIR filter with feedback coefficients -a1, -a2, ...         *)
  452. (*  The coding trick here is the use of Self.  That is,         *)
  453. (*  PastValues[Self, ...] will remain unevaluated until         *)
  454. (*  GetValue is called by the user.                 *)
  455. MyMakeSignal[IIR[n_, a__]] := MyMakeSignal[IIR[n, a], n]
  456. MyMakeSignal[IIR[n_, a__], n_] :=
  457.     Block [    {alist, index, len, signal, z = Global`z, zdenom, zerocount},
  458.         alist = ToList[a];
  459.         len = Length[alist];
  460.         signal = MakeDigitalSignal[n];
  461.         signal = StreamSignal[signal, 0, Infinity];
  462.         AddSlot[signal, False, IIRCoefficients, alist];
  463.         AddSlot[signal, True,  CurrentValue, 0];
  464.         If [ len <= 2,
  465.              AddSlot[signal, True, PastValues, 0],
  466.              AddSlot[signal, True, PastValues,
  467.                  Table[0, {zerocount, 2, len}]] ];
  468.         AddSlot[signal, False, TheFunction,
  469.             IIRFilter[PastValues[Self],
  470.                   First[alist],
  471.                   Rest[alist]][Impulse[n]]];
  472.         AddSlot[signal, False, PostUpdateFunction, IIRPostUpdate];
  473.         zdenom = alist[[1]] +
  474.              Apply[ Plus,
  475.                 Table[ -alist[[index]] z^(1-index),
  476.                        {index, 2, len} ] ];
  477.         zobject = ZTransData[ 1 / zdenom, Rminus[0],
  478.                       Rplus[Infinity], ZVariables[z] ];
  479.         AddSlot[signal, False, PrintName, IIR[n, a]];
  480.         AddSlot[signal, False, Head[zobject], GetArgs[zobject]] ]
  481.  
  482.  
  483. (*  S I G N A L     M E T H O D S  *)
  484.  
  485.  
  486.                (*  Fetching signal values  *)
  487.  
  488. (*  Fetch fetches a signal's value at the passed index:            *)
  489. (*    [1] the signal's PreUpdateFunction is called if it exists,    *)
  490. (*    [2] the signal's value at the passed index is calculated,    *)
  491. (*    [3] the signal's PostUpdateFunction is called if it exists.    *)
  492. (*  The new signal is returned, the signal value being placed in    *)
  493. (*  slot CurrentValue.                            *)
  494.  
  495. SetAttributes[Fetch, {HoldFirst}]
  496. SetAttributes[FetchArray, {HoldFirst}]
  497. SetAttributes[FetchNext, {HoldFirst}]
  498.  
  499. (*  Convert all multidimensional indices into a list form  *)
  500. Fetch[signal_, i1_, indices__] :=
  501.     Fetch[signal, {i1, indices}] /;
  502.     SignalQ[signal]
  503.  
  504. (*  Illegal to Fetch on an abstract signal or other non-computable signal  *)
  505. Fetch[signal_, index_] :=
  506.     Message[Fetch::notcomputable, Signal[slots]] /;
  507.     SignalQ[signal] && ! ComputableSignalQ[signal]
  508.  
  509. (*  Fetch on Pointwise signal  *)
  510. Fetch[signal_, index_] :=
  511.     Block [ {value},
  512.         value = GetValue[signal, index];
  513.         signal = WriteSlot[signal, CurrentValue, value];
  514.         value ] /;
  515.     PointwiseSignalQ[signal] 
  516.  
  517. (*  Fetch on Stream signal:  signal is not evaluated  *)
  518. FetchNext[signal_] :=
  519.     Block [    {index, newval},
  520.         If [ HasSlotQ[signal, PreUpdateFunction],
  521.              PreUpdateFunction[signal][signal],
  522.              AppendSlot[signal, CurrentIndex, Plus, 1] ];
  523.         index = CurrentIndex[signal];
  524.         signal = WriteSlot[signal, CurrentIndex, index];
  525.         newval = GetValue[signal, index];
  526.         WriteSlot[signal, CurrentValue, newval];
  527.         If [ HasSlotQ[signal, PostUpdateFunction],
  528.              PostUpdateFunction[signal][signal] ];
  529.         newval ] /;
  530.     StreamSignalQ[signal]
  531.  
  532. Fetch[signal_, endindex_] :=
  533.     Block [    {curindex, index},
  534.         curindex = CurrentIndex[signal];
  535.         nextfun = NextFun[signal];
  536.         If [ TrueQ[index < curindex],
  537.              signal = TableLookup[signal, curindex],
  538.              For [ index = curindex,
  539.                ! SameQ[index, endindex],
  540.                index = nextfun[index],
  541.                FetchNext[signal] ] ];
  542.         CurrentValue[signal] ] /;
  543.     StreamSignalQ[signal]
  544.  
  545. (*  Fetch on Array signal  *)
  546. FetchArray[signal_] :=
  547.     Block [ {table},
  548.         thevalue[subs__] := GetValue[signal, subs];
  549.         table = Array[thevalue, Length[signal], Start[signal]];
  550.         signal = AddSlot[signal, False, Array, table] ] /;
  551.     ArraySignalQ[signal]
  552.  
  553. Fetch[signal_, index_] :=
  554.     Block [    {value},
  555.         If [ ! HasSlotQ[signal, Array],
  556.              FetchArray[signal] ];
  557.         value = TableLookup[1 + index - Start[signal],
  558.                     Array[signal],
  559.                     Length[signal],
  560.                     OutOfDomainValue[signal] ];
  561.         signal = WriteSlot[signal, CurrentValue, value];
  562.         value ] /; 
  563.     ArraySignalQ[signal]
  564.  
  565.  
  566.             (*  Extensions of built-in functions  *)
  567.  
  568. (*  Format  *)
  569. Signal/: Format[ Signal[slots__] ] :=
  570.     PrintName[Signal[slots]] /;
  571.     HasSlotQ[Signal[slots], PrintName]
  572.  
  573.  
  574.             (*   Extensions to "DataType.m"    *)
  575.  
  576. Signal/: DataType[ Signal[slots__] ] :=
  577.         Signal[slots__] :> ReadSlot[Signal[slots], DataType] /;
  578.         HasSlotQ[Signal[slots], DataType]
  579. Signal/: DataType[ Signal[slots__] ] :=
  580.         ReadSlot[Signal[slots], TheFunction] /;
  581.         HasSlotQ[Signal[slots], TheFunction]
  582.  
  583. (*  ConstantQ  *)
  584. Signal/: ConstantQ[ Signal[slots__] ] :=
  585.     MyFreeQ[TheFunction[Signal[slots]], TimeVariables[Signal[slots]]]
  586.  
  587. (*  IsComplexQ  *)
  588. Signal/: IsComplexQ[ Signal[slots__] ] :=
  589.     SameQ[DataType[Signal[slots]], Complex]
  590.  
  591. (*  IsImaginaryQ  *)
  592. Signal/: IsImaginaryQ[ Signal[slots__] ] :=
  593.     SameQ[DataType[Signal[slots]], Imaginary]
  594.  
  595. (*  IsRealQ  *)
  596. Signal/: IsRealQ[ Signal[slots__] ] :=
  597.     SameQ[DataType[Signal[slots]], Real]
  598.  
  599.  
  600.             (*     Extensions of "SigProc.m"    *)
  601.  
  602. (*  Difference  *)
  603. Difference/: Expand[Difference[k_,n_][Signal[slots__]]] :=
  604.     Expand[Difference[k,n][TheFunction[Signal[slots]]]]
  605.  
  606. (*  Shift  *)
  607. Shift/: Expand[Shift[k_,n_][Signal[slots__]]] :=
  608.     Block [    {newsig},
  609.         newsig = Signal[slots];
  610.         vars = TimeVariables[newsig];
  611.         WriteSlot[newsig,
  612.               TheFunction,
  613.               TheFunction[newsig] /. vars -> vars + k] ]
  614.  
  615. (*  Summation  *)
  616. Signal/: Summation[i_][Signal[slots__]] :=
  617.     Summation[i, TimeVariables[Signal[slots]]] [Signal[slots]]
  618.  
  619. (*    Apply any operator to a Signal object -- without the semaphore,    *)
  620. (*  an infinite loop will result.  If the signal has a slot with the    *)
  621. (*  same name as the operator, the value of the slot is returned.    *)
  622. (*  Otherwise, it is assumed that operator is a method and the        *)
  623. (*  function operator will be applied to the signal.            *)
  624. Signal/: operator_[ Signal[slots__] ] :=
  625.     Block [ {result, signal},
  626.         Push[SignalOperatorSemaphore, operator];
  627.         signal = Signal[slots];
  628.         If [ HasSlotQ[signal, operator],
  629.              result = ReadSlot[signal, operator],
  630.              result = operator[signal] ];
  631.         Pop[SignalOperatorSemaphore];
  632.         result ] /;
  633.     ! MemberQ[SignalOperatorSemaphore, operator]
  634.  
  635.  
  636.         (*  Interface to the forward z-transform package  *)
  637. (*
  638. PrependTo[ZTransformInterfaceRules,
  639.       ztrans[x_, args__] :>
  640.         Which [    ! HasSlotQ[x, TheFunction],
  641.               MyMessage[ztransform::notcomputable, Null, x],
  642.             TrueQ[ DISCRETE[x] ],
  643.               ZTransform[ReadSlot[x, TheFunction]],
  644.             True,
  645.               MyMessage[ztransform::notdiscrete, Null, x] ] /;
  646.         SignalQ[x] ]
  647.  
  648. PrependTo[InvZTransformInterfaceRules,
  649.       zinverse[x_, args__] :>
  650.         InvZTransform[ReadSlot[x, ZTransData], args] /;
  651.         SignalQ[x] && HasSlotQ[x, ZTransData] ]
  652.  *)
  653.  
  654.  
  655. (*  D E F A U L T     S L O T     V A L U E S  *)
  656.  
  657. DefaultSlot[Signal, Bandwidth,        Infinity]
  658. DefaultSlot[Signal, CenterOfSymmetry,    None]
  659. DefaultSlot[Signal, DataType,        Complex]
  660. DefaultSlot[Signal, End,        Infinity]
  661. DefaultSlot[Signal, EndBandwidth,    Infinity]
  662. DefaultSlot[Signal, Period,        Infinity]
  663. DefaultSlot[Signal, Start,        -Infinity]
  664. DefaultSlot[Signal, StartBandwidth,    -Infinity]
  665. DefaultSlot[Signal, Support,        { -Infinity, Infinity } ]
  666. DefaultSlot[Signal, Symmetry,        None]
  667.  
  668. DefaultSlot[Signal, CurrentValue,    Null]
  669. DefaultSlot[Signal, Dimensions,        1]
  670. DefaultSlot[Signal, Length,        0]
  671. DefaultSlot[Signal, OutOfDomainValue,    0]
  672.  
  673.  
  674. (*  Determination of Variables  *)
  675. defaultsignalvars[x_, dv_, cv_] :=
  676.     Block [    {numdims},
  677.         numdims = ReadSlot[x, Dimensions];
  678.         Which [ TrueQ[ DISCRETE[x] ],
  679.               DummyVariables[numdims, dv],
  680.             TrueQ[ CONTINUOUS[x] ],
  681.               DummyVariables[numdims, cv],
  682.             True,
  683.               DummyVariables[numdims, dv] ] ]
  684.  
  685. TimeVariables[x_] :=
  686.     ReadSlot[x, TimeVariables] /;
  687.     HasSlotQ[x, TimeVariables]
  688. TimeVariables[x_] :=
  689.     defaultsignalvars[x, Global`n, Global`t] /;
  690.     HasSlotQ[x, Dimensions]
  691.  
  692. ZVariables[x_] :=
  693.     ReadSlot[x, ZVariables] /;
  694.     HasSlotQ[x, ZVariables]
  695. ZVariables[x_] :=
  696.     DummyVariables[Length[ReadSlot[x, TimeVariables]], z] /;
  697.     HasSlotQ[x, Dimensions] && DISCRETE[x] && HasSlotQ[x, TimeVariables]
  698.  
  699. FrequencyVariables[x_] :=
  700.     ReadSlot[x, FrequencyVariables] /;
  701.     HasSlotQ[x, FrequencyVariables]
  702. FrequencyVariables[x_] :=
  703.     defaultsignalvars[x, Global`k, Global`w] /;
  704.     HasSlotQ[x, Dimensions]
  705.  
  706.  
  707. (*  E N D     P A C K A G E  *)
  708.  
  709. End[]
  710. EndPackage[]
  711.  
  712. If [ TrueQ[ $VersionNumber >= 2.0 ],
  713.      On[ General::spell ];
  714.      On[ General::spell1 ] ];
  715.  
  716.  
  717. (*  W R I T E     P R O T E C T I O N  *)
  718.  
  719. Combine[ SPsignals, { ArraySignal, PointwiseSignal, StreamSignal } ]
  720.  
  721. Combine[SPfunctions,
  722.   List[    ArraySignalQ,        ComputableSignalQ,    IIRFilter,
  723.     MakeContinuousSignal,    MakeDigitalSignal,    MakeSignal,
  724.     PointwiseSignalQ,    SignalQ,        StreamSignalQ ] ]
  725.  
  726.  
  727. (*  E N D I N G     M E S S A G E  *)
  728.  
  729. Print[ "Signal objects are loaded." ]
  730. Null
  731.